package org.javaforever.poitranslator.core;

import java.io.FileInputStream;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Row;
import org.light.core.ApplicationContextXml;
import org.light.core.LayoutComb;
import org.light.core.ManyToManySerialComparator;
import org.light.core.Module;
import org.light.core.PrismInterface;
import org.light.core.ReportComb;
import org.light.core.SpringMVCController;
import org.light.domain.Domain;
import org.light.domain.DomainSerialComparator;
import org.light.domain.Dropdown;
import org.light.domain.Field;
import org.light.domain.ManyToMany;
import org.light.domain.Pair;
import org.light.domain.Prism;
import org.light.domain.Project;
import org.light.domain.ValidateInfo;
import org.light.easyuilayouts.widgets.Nav;
import org.light.exceltrnslator.LayoutExcelTranslator;
import org.light.exceltrnslator.ReportExcelTranslator;
import org.light.exceltrnslator.ShiroAuthExcelTranslator;
import org.light.exception.ValidateException;
import org.light.generator.DBDefinitionGenerator;
import org.light.generator.MysqlDBDefinitionGenerator;
import org.light.generator.PgsqlDBDefinitionGenerator;
import org.light.layouts.EasyUIHomePagePI;
import org.light.oracle.core.OracleDomainDecorator;
import org.light.oracle.core.OraclePrism;
import org.light.oracle.generator.Oracle11gDBDefinitionGenerator;
import org.light.utils.BooleanUtil;
import org.light.utils.DomainUtil;
import org.light.utils.StringUtil;

public class ProjectExcelWorkBook {
	protected Project project;
	protected String username;
	protected String password;
	protected String filename;

	protected final static String[] forbiddenwords = { "abstract", "assert", "boolean", "break", "byte", "case",
			"catch", "char", "class", "const", "continue", "default", "do", "double", "else", "enum", "extends",
			"final", "finally", "float", "for", "if",

			"implements", "import", "instanceof", "int", "interface", "long", "native", "new", "package", "private",
			"protected", "public", "return", "short", "static", "strictfp", "super", "switch",

			"synchronized", "this", "throw", "throws", "transient", "try", "void", "volatile", "while", "byValue",
			"cast", "false", "future", "generic", "inner", "operator", "outer", "rest", "true", "var", "goto", "const",
			"null", "image" };

	protected final static String[] sqlKeyWords = { "alter", "and", "as", "asc", "between", "by", "count", "create",
			"delete", "desc", "distinct", "drop", "from", "group", "having", "in", "insert", "into", "is", "join",
			"like", "not", "on", "or", "order", "select", "set", "table", "union", "update", "values", "where", "limit",
			"bool", "boolean", "bit", "blob", "enum", "long", "longblob", "longtext", "medium", "mediumblob",
			"mediumint", "mediumtext", "time", "timestamp", "tinyblob", "tinyint", "tinytext", "text", "bigint", "int",
			"int1", "int2", "int3", "int4", "int8", "integer", "float", "float4", "float8", "double", "char",
			"varbinary", "varchar", "varcharacter", "precision", "real", "date", "datetime", "year", "unsigned",
			"signed", "decimal", "numeric", "false", "true", "null", "unknown", "date", "time", "timestamp", "video" };
	
	protected final static String[] oracleKeyWords = { "A","ABORT","ACCESS","ACCESSED","ACCOUNT","ACTIVATE","ADD","ADMIN",
			"ADMINISTER","ADMINISTRATOR","ADVISE","ADVISOR","AFTER","ALGORITHM","ALIAS","ALL","ALLOCATE","ALLOW","ALL_ROWS",
			"ALTER","ALWAYS","ANALYZE","ANCILLARY","AND","AND_EQUAL","ANTIJOIN","ANY","APPEND","APPLY","ARCHIVE","ARCHIVELOG",
			"ARRAY","AS","ASC","ASSOCIATE","AT","ATTRIBUTE","ATTRIBUTES","AUDIT","AUTHENTICATED","AUTHENTICATION","AUTHID",
			"AUTHORIZATION","AUTO","AUTOALLOCATE","AUTOEXTEND","AUTOMATIC","AVAILABILITY","BACKUP","BECOME","BEFORE","BEGIN",
			"BEHALF","BETWEEN","BFILE","BIGFILE","BINARY_DOUBLE","BINARY_DOUBLE_INFINITY","BINARY_DOUBLE_NAN","BINARY_FLOAT",
			"BINARY_FLOAT_INFINITY","BINARY_FLOAT_NAN","BINDING","BITMAP","BITS","BLOB","BLOCK","BLOCKS","BLOCKSIZE","BLOCK_RANGE",
			"BODY","BOTH","BOUND","BROADCAST","BUFFER","BUFFER_CACHE","BUFFER_POOL","BUILD","BULK","BY","BYPASS_RECURSIVE_CHECK",
			"BYPASS_UJVC","BYTE","CACHE","CACHE_CB","CACHE_INSTANCES","CACHE_TEMP_TABLE","CALL","CANCEL","CARDINALITY","CASCADE",
			"CASE","CAST","CATEGORY","CERTIFICATE","CFILE","CHAINED","CHANGE","CHAR","CHARACTER","CHAR_CS","CHECK","CHECKPOINT",
			"CHILD","CHOOSE","CHUNK","CIV_GB","CLASS","CLEAR","CLOB","CLONE","CLOSE","CLOSE_CACHED_OPEN_CURSORS","CLUSTER",
			"CLUSTERING_FACTOR","COALESCE","COARSE","COLLECT","COLLECTIONS_GET_REFS","COLUMN","COLUMNS","COLUMN_STATS","COLUMN_VALUE",
			"COMMENT","COMMIT","COMMITTED","COMPACT","COMPATIBILITY","COMPILE","COMPLETE","COMPOSITE_LIMIT","COMPRESS","COMPUTE",
			"CONFORMING","CONNECT","CONNECT_BY_ISCYCLE","CONNECT_BY_ISLEAF","CONNECT_BY_ROOT","CONNECT_TIME","CONSIDER","CONSISTENT",
			"CONSTRAINT","CONSTRAINTS","CONTAINER","CONTENT","CONTENTS","CONTEXT","CONTINUE","CONTROLFILE","CONVERT","CORRUPTION",
			"COST","CPU_COSTING","CPU_PER_CALL","CPU_PER_SESSION","CREATE","CREATE_STORED_OUTLINES","CROSS","CUBE","CUBE_GB","CURRENT",
			"CURRENT_DATE","CURRENT_SCHEMA","CURRENT_TIME","CURRENT_TIMESTAMP","CURRENT_USER","CURSOR","CURSOR_SHARING_EXACT",
			"CURSOR_SPECIFIC_SEGMENT","CYCLE","DANGLING","DATA","DATABASE","DATAFILE","DATAFILES","DATAOBJNO","DATE","DATE_MODE",
			"DAY","DBA","DBA_RECYCLEBIN","DBTIMEZONE","DDL","DEALLOCATE","DEBUG","DEC","DECIMAL","DECLARE","DECREMENT","DEFAULT",
			"DEFERRABLE","DEFERRED","DEFINED","DEFINER","DEGREE","DELAY","DELETE","DEMAND","DENSE_RANK","DEREF","DEREF_NO_REWRITE",
			"DESC","DETACHED","DETERMINES","DICTIONARY","DIMENSION","DIRECTORY","DISABLE","DISASSOCIATE","DISCONNECT","DISK",
			"DISKGROUP","DISKS","DISMOUNT","DISTINCT","DISTINGUISHED","DISTRIBUTED","DML","DML_UPDATE","DOCUMENT","DOMAIN_INDEX_NO_SORT",
			"DOMAIN_INDEX_SORT","DOUBLE","DOWNGRADE","DRIVING_SITE","DROP","DUMP","DYNAMIC","DYNAMIC_SAMPLING","DYNAMIC_SAMPLING_EST_CDN",
			"EACH","ELEMENT","ELSE","EMPTY","ENABLE","ENCRYPTED","ENCRYPTION","END","ENFORCE","ENFORCED","ENTRY","ERROR","ERROR_ON_OVERLAP_TIME",
			"ESCAPE","ESTIMATE","EVENTS","EXCEPT","EXCEPTIONS","EXCHANGE","EXCLUDING","EXCLUSIVE","EXECUTE","EXEMPT","EXISTS","EXPAND_GSET_TO_UNION",
			"EXPIRE","EXPLAIN","EXPLOSION","EXPORT","EXPR_CORR_CHECK","EXTEND","EXTENDS","EXTENT","EXTENTS","EXTERNAL","EXTERNALLY","EXTRACT","FACT",
			"FAILED","FAILED_LOGIN_ATTEMPTS","FAILGROUP","FALSE","FAST","FBTSCAN","FIC_CIV","FIC_PIV","FILE","FILTER","FINAL","FINE","FINISH","FIRST",
			"FIRST_ROWS","FLAGGER","FLASHBACK","FLOAT","FLOB","FLUSH","FOLLOWING","FOR","FORCE","FORCE_XML_QUERY_REWRITE","FOREIGN","FREELIST",
			"FREELISTS","FREEPOOLS","FRESH","FROM","FULL","FUNCTION","FUNCTIONS","GATHER_PLAN_STATISTICS","GBY_CONC_ROLLUP","GENERATED","GLOBAL",
			"GLOBALLY","GLOBAL_NAME","GLOBAL_TOPIC_ENABLED","GRANT","GROUP","GROUPING","GROUPS","GROUP_BY","GUARANTEE","GUARANTEED","GUARD","HASH",
			"HASHKEYS","HASH_AJ","HASH_SJ","HAVING","HEADER","HEAP","HIERARCHY","HIGH","HINTSET_BEGIN","HINTSET_END","HOUR","HWM_BROKERED",
			"IDENTIFIED","IDENTIFIER","IDENTITY","IDGENERATORS","IDLE_TIME","IF","IGNORE","IGNORE_ON_CLAUSE","IGNORE_OPTIM_EMBEDDED_HINTS",
			"IGNORE_WHERE_CLAUSE","IMMEDIATE","IMPORT","IN","INCLUDE_VERSION","INCLUDING","INCREMENT","INCREMENTAL","INDEX","INDEXED","INDEXES",
			"INDEXTYPE","INDEXTYPES","INDEX_ASC","INDEX_COMBINE","INDEX_DESC","INDEX_FFS","INDEX_FILTER","INDEX_JOIN","INDEX_ROWS","INDEX_RRS",
			"INDEX_SCAN","INDEX_SKIP_SCAN","INDEX_SS","INDEX_SS_ASC","INDEX_SS_DESC","INDEX_STATS","INDICATOR","INFINITE","INFORMATIONAL","INITIAL",
			"INITIALIZED","INITIALLY","INITRANS","INLINE","INNER","INSERT","INSTANCE","INSTANCES","INSTANTIABLE","INSTANTLY","INSTEAD","INT",
			"INTEGER","INTEGRITY","INTERMEDIATE","INTERNAL_CONVERT","INTERNAL_USE","INTERPRETED","INTERSECT","INTERVAL","INTO","INVALIDATE",
			"IN_MEMORY_METADATA","IS","ISOLATION","ISOLATION_LEVEL","ITERATE","ITERATION_NUMBER","JAVA","JOB","JOIN","KEEP","KERBEROS","KEY",
			"KEYFILE","KEYS","KEYSIZE","KEY_LENGTH","KILL","LAST","LATERAL","LAYER","LDAP_REGISTRATION","LDAP_REGISTRATION_ENABLED",
			"LDAP_REG_SYNC_INTERVAL","LEADING","LEFT","LENGTH","LESS","LEVEL","LEVELS","LIBRARY","LIKE","LIKE2","LIKE4","LIKEC","LIKE_EXPAND",
			"LIMIT","LINK","LIST","LOB","LOCAL","LOCALTIME","LOCALTIMESTAMP","LOCAL_INDEXES","LOCATION","LOCATOR","LOCK","LOCKED","LOG","LOGFILE",
			"LOGGING","LOGICAL","LOGICAL_READS_PER_CALL","LOGICAL_READS_PER_SESSION","LOGOFF","LOGON","LONG","MAIN","MANAGE","MANAGED","MANAGEMENT",
			"MANUAL","MAPPING","MASTER","MATCHED","MATERIALIZE","MATERIALIZED","MAX","MAXARCHLOGS","MAXDATAFILES","MAXEXTENTS","MAXIMIZE","MAXINSTANCES",
			"MAXLOGFILES","MAXLOGHISTORY","MAXLOGMEMBERS","MAXSIZE","MAXTRANS","MAXVALUE","MEASURES","MEMBER","MEMORY","MERGE","MERGE_AJ","MERGE_CONST_ON",
			"MERGE_SJ","METHOD","MIGRATE","MIN","MINEXTENTS","MINIMIZE","MINIMUM","MINUS","MINUTE","MINVALUE","MIRROR","MLSLABEL","MODE","MODEL",
			"MODEL_DONTVERIFY_UNIQUENESS","MODEL_MIN_ANALYSIS","MODEL_NO_ANALYSIS","MODEL_PBY","MODEL_PUSH_REF","MODIFY","MONITORING","MONTH","MOUNT","MOVE",
			"MOVEMENT","MULTISET","MV_MERGE","NAME","NAMED","NAN","NATIONAL","NATIVE","NATURAL","NAV","NCHAR","NCHAR_CS","NCLOB","NEEDED","NESTED",
			"NESTED_TABLE_FAST_INSERT","NESTED_TABLE_GET_REFS","NESTED_TABLE_ID","NESTED_TABLE_SET_REFS","NESTED_TABLE_SET_SETID","NETWORK","NEVER","NEW",
			"NEXT","NLS_CALENDAR","NLS_CHARACTERSET","NLS_COMP","NLS_CURRENCY","NLS_DATE_FORMAT","NLS_DATE_LANGUAGE","NLS_ISO_CURRENCY","NLS_LANG",
			"NLS_LANGUAGE","NLS_LENGTH_SEMANTICS","NLS_NCHAR_CONV_EXCP","NLS_NUMERIC_CHARACTERS","NLS_SORT","NLS_SPECIAL_CHARS","NLS_TERRITORY","NL_AJ",
			"NL_SJ","NO","NOAPPEND","NOARCHIVELOG","NOAUDIT","NOCACHE","NOCOMPRESS","NOCPU_COSTING","NOCYCLE","NODELAY","NOFORCE","NOGUARANTEE","NOLOGGING",
			"NOMAPPING","NOMAXVALUE","NOMINIMIZE","NOMINVALUE","NOMONITORING","NONE","NOORDER","NOOVERRIDE","NOPARALLEL","NOPARALLEL_INDEX","NORELY","NOREPAIR",
			"NORESETLOGS","NOREVERSE","NOREWRITE","NORMAL","NOROWDEPENDENCIES","NOSEGMENT","NOSORT","NOSTRICT","NOSWITCH","NOT","NOTHING","NOVALIDATE","NOWAIT",
			"NO_ACCESS","NO_BASETABLE_MULTIMV_REWRITE","NO_BUFFER","NO_CPU_COSTING","NO_EXPAND","NO_EXPAND_GSET_TO_UNION","NO_FACT","NO_FILTERING","NO_INDEX",
			"NO_INDEX_FFS","NO_INDEX_SS","NO_MERGE","NO_MODEL_PUSH_REF","NO_MONITORING","NO_MULTIMV_REWRITE","NO_ORDER_ROLLUPS","NO_PARALLEL","NO_PARALLEL_INDEX",
			"NO_PARTIAL_COMMIT","NO_PRUNE_GSETS","NO_PUSH_PRED","NO_PUSH_SUBQ","NO_QKN_BUFF","NO_QUERY_TRANSFORMATION","NO_REF_CASCADE","NO_REWRITE","NO_SEMIJOIN",
			"NO_SET_TO_JOIN","NO_STAR_TRANSFORMATION","NO_STATS_GSETS","NO_SWAP_JOIN_INPUTS","NO_TRIGGER","NO_UNNEST","NO_USE_HASH","NO_USE_MERGE","NO_USE_NL",
			"NO_XML_QUERY_REWRITE","NULL","NULLS","NUMBER","NUMERIC","NVARCHAR2","OBJECT","OBJNO","OBJNO_REUSE","OF","OFF","OFFLINE","OID","OIDINDEX","OLD","ON",
			"ONLINE","ONLY","OPAQUE","OPAQUE_TRANSFORM","OPAQUE_XCANONICAL","OPCODE","OPEN","OPERATOR","OPTIMAL","OPTIMIZER_FEATURES_ENABLE","OPTIMIZER_GOAL",
			"OPTION","OPT_ESTIMATE","OR","ORA_ROWSCN","ORDER","ORDERED","ORDERED_PREDICATES","ORGANIZATION","OR_EXPAND","OUTER","OUTLINE","OUT_OF_LINE","OVER",
			"OVERFLOW","OVERFLOW_NOMOVE","OVERLAPS","OWN","PACKAGE","PACKAGES","PARALLEL","PARALLEL_INDEX","PARAMETERS","PARENT","PARITY","PARTIALLY","PARTITION",
			"PARTITIONS","PARTITION_HASH","PARTITION_LIST","PARTITION_RANGE","PASSWORD_GRACE_TIME","PASSWORD_LIFE_TIME","PASSWORD_LOCK_TIME",
			"PASSWORD_REUSE_MAX","PASSWORD_REUSE_TIME","PASSWORD_VERIFY_FUNCTION","PCTFREE","PCTINCREASE","PCTTHRESHOLD","PCTUSED","PCTVERSION","PERCENT",
			"PERFORMANCE","PERMANENT","PFILE","PHYSICAL","PIV_GB","PIV_SSF","PLAN","PLSQL_CODE_TYPE","PLSQL_DEBUG","PLSQL_OPTIMIZE_LEVEL","PLSQL_WARNINGS",
			"POLICY","POST_TRANSACTION","POWER","PQ_DISTRIBUTE","PQ_MAP","PQ_NOMAP","PREBUILT","PRECEDING","PRECISION","PREPARE","PRESENT","PRESERVE","PRIMARY",
			"PRIOR","PRIVATE","PRIVATE_SGA","PRIVILEGE","PRIVILEGES","PROCEDURE","PROFILE","PROGRAM","PROJECT","PROTECTED","PROTECTION","PUBLIC","PURGE",
			"PUSH_PRED","PUSH_SUBQ","PX_GRANULE","QB_NAME","QUERY","QUERY_BLOCK","QUEUE","QUEUE_CURR","QUEUE_ROWP","QUIESCE","QUOTA","RANDOM","RANGE","RAPIDLY",
			"RAW","RBA","READ","READS","REAL","REBALANCE","REBUILD","RECORDS_PER_BLOCK","RECOVER","RECOVERABLE","RECOVERY","RECYCLE","RECYCLEBIN","REDUCED",
			"REDUNDANCY","REF","REFERENCE","REFERENCED","REFERENCES","REFERENCING","REFRESH","REF_CASCADE_CURSOR","REGEXP_LIKE","REGISTER","REJECT","REKEY",
			"RELATIONAL","RELY","REMOTE_MAPPED","RENAME","REPAIR","REPLACE","REQUIRED","RESET","RESETLOGS","RESIZE","RESOLVE","RESOLVER","RESOURCE","RESTORE_AS_INTERVALS",
			"RESTRICT","RESTRICTED","RESTRICT_ALL_REF_CONS","RESUMABLE","RESUME","RETENTION","RETURN","RETURNING","REUSE","REVERSE","REVOKE","REWRITE","REWRITE_OR_ERROR",
			"RIGHT","ROLE","ROLES","ROLLBACK","ROLLUP","ROW","ROWDEPENDENCIES","ROWID","ROWNUM","ROWS","ROW_LENGTH","RULE","RULES","SAMPLE","SAVEPOINT","SAVE_AS_INTERVALS",
			"SB4","SCALE","SCALE_ROWS","SCAN","SCAN_INSTANCES","SCHEDULER","SCHEMA","SCN","SCN_ASCENDING","SCOPE","SD_ALL","SD_INHIBIT","SD_SHOW","SECOND","SECURITY","SEED",
			"SEGMENT","SEG_BLOCK","SEG_FILE","SELECT","SELECTIVITY","SEMIJOIN","SEMIJOIN_DRIVER","SEQUENCE","SEQUENCED","SEQUENTIAL","SERIALIZABLE","SERVERERROR","SESSION",
			"SESSIONS_PER_USER","SESSIONTIMEZONE","SESSIONTZNAME","SESSION_CACHED_CURSORS","SET","SETS","SETTINGS","SET_TO_JOIN","SEVERE","SHARE","SHARED","SHARED_POOL",
			"SHRINK","SHUTDOWN","SIBLINGS","SID","SIMPLE","SINGLE","SINGLETASK","SIZE","SKIP","SKIP_EXT_OPTIMIZER","SKIP_UNQ_UNUSABLE_IDX","SKIP_UNUSABLE_INDEXES",
			"SMALLFILE","SMALLINT","SNAPSHOT","SOME","SORT","SOURCE","SPACE","SPECIFICATION","SPFILE","SPLIT","SPREADSHEET","SQL","SQLLDR","SQL_TRACE","STANDBY","STAR",
			"START","STARTUP","STAR_TRANSFORMATION","STATEMENT_ID","STATIC","STATISTICS","STOP","STORAGE","STORE","STREAMS","STRICT","STRIP","STRUCTURE","SUBMULTISET",
			"SUBPARTITION","SUBPARTITIONS","SUBPARTITION_REL","SUBSTITUTABLE","SUCCESSFUL","SUMMARY","SUPPLEMENTAL","SUSPEND","SWAP_JOIN_INPUTS","SWITCH","SWITCHOVER",
			"SYNONYM","SYSAUX","SYSDATE","SYSDBA","SYSOPER","SYSTEM","SYSTIMESTAMP","SYS_DL_CURSOR","SYS_FBT_INSDEL","SYS_OP_BITVEC","SYS_OP_CAST","SYS_OP_COL_PRESENT",
			"SYS_OP_ENFORCE_NOT_NULL$","SYS_OP_MINE_VALUE","SYS_OP_NOEXPAND","SYS_OP_NTCIMG$","SYS_PARALLEL_TXN","SYS_RID_ORDER","TABLE","TABLES","TABLESPACE","TABLESPACE_NO",
			"TABLE_STATS","TABNO","TEMPFILE","TEMPLATE","TEMPORARY","TEST","THAN","THE","THEN","THREAD","THROUGH","TIME","TIMEOUT","TIMESTAMP","TIMEZONE_ABBR","TIMEZONE_HOUR",
			"TIMEZONE_MINUTE","TIMEZONE_REGION","TIME_ZONE","TIV_GB","TIV_SSF","TO","TOPLEVEL","TRACE","TRACING","TRACKING","TRAILING","TRANSACTION","TRANSITIONAL","TREAT",
			"TRIGGER","TRIGGERS","TRUE","TRUNCATE","TRUSTED","TUNING","TX","TYPE","TYPES","TZ_OFFSET","UB2","UBA","UID","UNARCHIVED","UNBOUND","UNBOUNDED","UNDER","UNDO",
			"UNDROP","UNIFORM","UNION","UNIQUE","UNLIMITED","UNLOCK","UNNEST","UNPACKED","UNPROTECTED","UNQUIESCE","UNRECOVERABLE","UNTIL","UNUSABLE","UNUSED","UPDATABLE",
			"UPDATE","UPDATED","UPD_INDEXES","UPD_JOININDEX","UPGRADE","UPSERT","UROWID","USAGE","USE","USER","USER_DEFINED","USER_RECYCLEBIN","USE_ANTI","USE_CONCAT",
			"USE_HASH","USE_MERGE","USE_NL","USE_NL_WITH_INDEX","USE_PRIVATE_OUTLINES","USE_SEMI","USE_STORED_OUTLINES","USE_TTT_FOR_GSETS","USE_WEAK_NAME_RESL","USING",
			"VALIDATE","VALIDATION","VALUE","VALUES","VARCHAR","VARCHAR2","VARRAY","VARYING","VECTOR_READ","VECTOR_READ_TRACE","VERSION","VERSIONS","VIEW","WAIT","WELLFORMED",
			"WHEN","WHENEVER","WHERE","WHITESPACE","WITH","WITHIN","WITHOUT","WORK","WRITE","XID","XMLATTRIBUTES","XMLCOLATTVAL","XMLELEMENT","XMLFOREST","XMLPARSE","XMLSCHEMA",
			"XMLTYPE","X_DYN_PRUNE","YEAR","ZONE","RANK"};
	
	public static boolean isSqlKeyword(String notion) {
		for (String word : sqlKeyWords) {
			if (word.equalsIgnoreCase(notion))
				return true;
		}
		return false;
	}

	public static boolean isForbidden(String notion) {
		for (String word : forbiddenwords) {
			if (word.equals(notion))
				return true;
		}
		return false;
	}
	
	public static boolean isOracleKeyword(String notion) {
		for (String word : oracleKeyWords) {
			if (word.equalsIgnoreCase(notion))
				return true;
		}
		return false;
	}

	public static void decorateDropdowns(List<Domain> domainList) throws ValidateException {
		for (Domain d : domainList) {
			for (Field f : d.getFieldsWithoutId()) {
				if (f instanceof Dropdown) {
					Dropdown dp = (Dropdown) f;
					Domain t = DomainUtil.findDomainInList(domainList, dp.getTargetName());
					dp.decorate(t);
				}
			}
		}
	}
	
	public static Domain decorateDomainDropdowns(Domain domain,List<Domain> domainList) throws ValidateException {
		for (Field f : domain.getFieldsWithoutId()) {
			if (f instanceof Dropdown) {
				Dropdown dp = (Dropdown) f;
				Domain t = DomainUtil.findDomainInList(domainList, dp.getTargetName());
				dp.decorate(t);
			}
		}
		return domain;
	}

	public static List<Prism> generatePrismsByDomains(List<Domain> domainList, DBDefinitionGenerator dbdg,
			Project project, Boolean ignoreWarning) throws Exception {
		if (project.getDbType() == null || "".equals(project.getDbType())
				|| "mysql".equalsIgnoreCase(project.getDbType()) || "mariadb".equalsIgnoreCase(project.getDbType())
				|| "postgresql".equalsIgnoreCase(project.getDbType())
				|| "pgsql".equalsIgnoreCase(project.getDbType())) {
			List<Prism> prisms = new ArrayList<Prism>();
			Set<Domain> projectDomainSet = new TreeSet<Domain>();
			projectDomainSet.addAll(domainList);
			for (Domain d : domainList) {
				d.decorateDomainWithLabels();
				Prism p = new Prism();
				p.setPackageToken(d.getPackageToken());
				p.setStandardName(d.getCapFirstDomainName() + "Prism");
				p.setDomain(d);
				p.setDbDefinitionGenerator(dbdg);
				p.setProjectDomains(projectDomainSet);
				p.setResolution(project.getResolution());
				p.setTitle(project.getTitle());
				p.setSubTitle(project.getSubTitle());
				p.setFooter(project.getFooter());
				p.setCrossOrigin(project.getCrossOrigin());
				p.setTechnicalStack(project.getTechnicalstack());
				if ("postgresql".equalsIgnoreCase(project.getDbType())
						|| "pgsql".equalsIgnoreCase(project.getDbType())) {
					p.generatePgPrismFromDomain(ignoreWarning);
				} else {
					p.generatePrismFromDomain(ignoreWarning);
				}
				prisms.add(p);
			}
			return prisms;
		} else if ("oracle".equalsIgnoreCase(project.getDbType())) {
			List<Prism> prisms = new ArrayList<Prism>();
			Set<Domain> projectDomainSet = new TreeSet<Domain>();
			projectDomainSet.addAll(domainList);
			for (Domain d : domainList) {
				d.decorateDomainWithLabels();
				OraclePrism p = new OraclePrism();
				p.setTechnicalStack(project.getTechnicalstack());
				p.setPackageToken(d.getPackageToken());
				p.setStandardName(d.getCapFirstDomainName() + "Prism");
				p.setDomain(OracleDomainDecorator.decorateOracleDomain(d));
				p.setDbDefinitionGenerator(dbdg);
				p.setProjectDomains(OracleDomainDecorator.decorateOracleDomainSet(projectDomainSet));
				p.setResolution(project.getResolution());
				p.setTitle(project.getTitle());
				p.setSubTitle(project.getSubTitle());
				p.setFooter(project.getFooter());
				p.setCrossOrigin(project.getCrossOrigin());
				p.generatePrismFromDomain(ignoreWarning);
				prisms.add(p);
			}
			return prisms;
		} else {
			ValidateInfo info = new ValidateInfo();
			info.addCompileError("未支持的数据库类型。");
			throw new ValidateException(info);
		}
	}

	public static Domain findDomainFromListByStandardName(List<Domain> domainList, String standardName)
			throws ValidateException {
		for (Domain d : domainList) {
			if (d.getStandardName().equals(standardName))
				return d;
		}
		ValidateInfo info = new ValidateInfo();
		info.addCompileError("在域对象列表找不到域对象" + standardName + "。");
		throw new ValidateException(info);
	}

	public Project pureTranslate(HSSFWorkbook book, boolean ignoreWarning) throws Exception {
		try {
			project = new Project();
			project = translateProjectMetaData(book.getSheet("project"), project);
			List<Domain> domainList = new ArrayList<Domain>();
			List<List<Domain>> dataDomainList = new ArrayList<>();
			ArrayList<Domain> dataList = new ArrayList<Domain>();

			ValidateInfo info0 = new ValidateInfo();
			for (int i = 1; i < book.getNumberOfSheets(); i++) {
				try {
					HSSFSheet sheet = book.getSheetAt(i);
					if (sheet.getSheetName().toLowerCase().contains("domain")) {
						Domain domain = translateDomain(sheet, project.getDbType(), ignoreWarning);
						domain.setSerial(i * 1000L);
						domain.setDbPrefix(project.getDbPrefix());
						domain.setPackageToken(project.getPackageToken());
						domain.setLanguage(project.getLanguage());
						domain.setSchema(project.getSchema());
						domain.setDomainSuffix(project.getDomainSuffix());
						domain.setDomainNamingSuffix(project.getDomainNamingSuffix());
						domain.setDaoSuffix(project.getDaoSuffix());
						domain.setDaoimplSuffix(project.getDaoimplSuffix());
						domain.setServiceSuffix(project.getServiceSuffix());
						domain.setServiceimplSuffix(project.getServiceimplSuffix());
						domain.setControllerSuffix(project.getControllerSuffix());
						domain.setControllerNamingSuffix(project.getControllerNamingSuffix());
						if (project.getTechnicalstack().equalsIgnoreCase("smeu")
								|| project.getTechnicalstack().equalsIgnoreCase("msmeu")) {
							domain.setControllerPackage(project.getControllerSuffix());
						}

						dataList = new ArrayList<Domain>();
						dataList.addAll(readDomainListWithData(sheet, domain, project.getDbType(), ignoreWarning));
						domainList.add(domain);
						dataDomainList.add(dataList);
					}
				} catch (ValidateException e) {
					info0.addAllCompileErrors(e.getValidateInfo().getCompileErrors());
					info0.addAllCompileWarnings(e.getValidateInfo().getCompileWarnings());
								}
			}
			if (!info0.success(ignoreWarning))
				throw new ValidateException(info0);
			decorateDropdowns(domainList);
			project.setDomains(domainList);
			decorateMtmDomainList(project.getDataDomains(), domainList);
			project.setDataDomains(dataDomainList);
			
			ValidateInfo combInfos = new ValidateInfo();
			for (int i = 1; i < book.getNumberOfSheets(); i++) {
				try {
					HSSFSheet sheet = book.getSheetAt(i);
					if (sheet.getSheetName().toLowerCase().contains("module")) {
						org.light.core.Module m = translateModule(project, sheet, domainList, project.getDataDomains());
						project.addModule(m);						
					}
					if (sheet.getSheetName().toLowerCase().contains("layout")) {
						LayoutComb lcm = translateLayout(project, sheet, domainList, project.getDataDomains());
						lcm.setTitles(project.getTitle(), project.getSubTitle(), project.getFooter());
						lcm.setTechnicalStack(project.getTechnicalstack());
						project.addLayoutComb(lcm);
					}
					if (sheet.getSheetName().toLowerCase().contains("report")) {
						ReportComb rcm = translateReport(project, sheet, domainList, project.getDataDomains());
						rcm.setTitles(project.getTitle(), project.getSubTitle(), project.getFooter());
						rcm.setTechnicalStack(project.getTechnicalstack());
						project.addReportComb(rcm);
					}
				}catch (ValidateException ve) {
					combInfos.addAllCompileErrors(ve.getValidateInfo().getCompileErrors());
					combInfos.addAllCompileWarnings(ve.getValidateInfo().getCompileWarnings());
				}
			}
			
			if (!combInfos.success(ignoreWarning))
				throw new ValidateException(combInfos);

			return project;
		} catch (ValidateException e) {
			ValidateInfo info = e.getValidateInfo();
			throw e;
		}
	}
	
	public ValidateInfo bookingValidateDomainNames(List<String> domainNames,List<Domain> domains) throws ValidateException{
		ValidateInfo info = new ValidateInfo();
		if (domainNames==null||domainNames.size()==0||domains==null||domains.size()==0) {
			info.addCompileWarning("生成的结果为空，或未做簿记！");
		}else if (domainNames.size()!=domains.size()) {
			info.addCompileWarning("簿记域对象清单总数不符！");
		}
		for (String domainName:domainNames) {
			if (!DomainUtil.nameExistsInDomainList(domainName,domains)) {
				info.addCompileError("簿记域对象"+domainName+"未正确解析！");
			}
		}
		return info;
	}

	public Project translate(HSSFWorkbook book, boolean ignoreWarning) throws Exception {
		project = new Project();
		project = translateProjectMetaData(book.getSheet("project"), project);
		List<Domain> domainList = new ArrayList<Domain>();

		ValidateInfo info0 = new ValidateInfo();
		for (int i = 1; i < book.getNumberOfSheets(); i++) {
			try {
				HSSFSheet sheet = book.getSheetAt(i);
				String sheetName = sheet.getSheetName();
				if (sheetName.startsWith("Sheet")) {
					info0.addCompileWarning("页签"+sheetName+"未恰当命名！");
				}else if (!sheetName.startsWith("Domain")&&!sheetName.startsWith("Module")&&!sheetName.startsWith("Layout")&&!sheetName.startsWith("Report")) {
					info0.addCompileWarning("页签"+sheetName+"的类型未支持！");
				}
				if (sheet.getSheetName().toLowerCase().contains("domain")) {
					String domainName = readMetaField(sheet, "domain", project.getDbType());
					project.addDomainName(domainName);
					Domain domain = translateDomain(sheet, project.getDbType(), ignoreWarning);
					
					domain.setSerial(i * 1000L);
					domain.setDbPrefix(project.getDbPrefix());
					domain.setPackageToken(project.getPackageToken());
					domain.setLanguage(project.getLanguage());
					domain.setSchema(project.getSchema());
					domain.setDomainSuffix(project.getDomainSuffix());
					domain.setDomainNamingSuffix(project.getDomainNamingSuffix());
					domain.setDaoSuffix(project.getDaoSuffix());
					domain.setDaoimplSuffix(project.getDaoimplSuffix());
					domain.setServiceSuffix(project.getServiceSuffix());
					domain.setServiceimplSuffix(project.getServiceimplSuffix());
					domain.setControllerSuffix(project.getControllerSuffix());
					domain.setControllerNamingSuffix(project.getControllerNamingSuffix());
					domain.setProjectName(project.getStandardName());
					domain.setDbType(project.getDbType());
					if (project.getTechnicalstack().equalsIgnoreCase("smeu")
							|| project.getTechnicalstack().equalsIgnoreCase("msmeu")) {
						domain.setControllerPackage(project.getControllerSuffix());
					}
					// output data
					ArrayList<Domain> dataList = new ArrayList<Domain>();
					dataList.addAll(readDomainListWithData(sheet, domain, project.getDbType(), ignoreWarning));
					project.addDataDomains(dataList);
					// end ouput
					domainList.add(domain);
				}
			} catch (ValidateException e) {
				info0.addAllCompileErrors(e.getValidateInfo().getCompileErrors());
				info0.addAllCompileWarnings(e.getValidateInfo().getCompileWarnings());
			}
		}
		
		if ("oracle".equalsIgnoreCase(project.getDbType())) {
			domainList=OracleDomainDecorator.decorateOracleDomainList(domainList);
		}
		
		decorateDomainsMtms(domainList);
		List<ValidateInfo> bookinginfos = new ArrayList<ValidateInfo>();
		ValidateInfo bookingInfo = bookingValidateDomainNames(project.getDomainNames(),domainList);
		bookinginfos.add(info0);
		bookinginfos.add(bookingInfo);
		ValidateInfo finalBookinginfo = ValidateInfo.mergeValidateInfo(bookinginfos, ignoreWarning);
		if (!finalBookinginfo.isSuccess(ignoreWarning)) throw new ValidateException(finalBookinginfo);
		
		Nav nav = new Nav();
		Set<Domain> navDomains = new TreeSet<>(new DomainSerialComparator());
		navDomains.addAll(domainList);
		nav.setDomains(navDomains);
		nav.setMtms(getMtmsFromDomains(domainList));
		project.setNav(nav);

		ValidateInfo combInfos = new ValidateInfo();
		for (int i = 1; i < book.getNumberOfSheets(); i++) {
			try {
				HSSFSheet sheet = book.getSheetAt(i);
				if (sheet.getSheetName().toLowerCase().contains("module")) {
					org.light.core.Module m = translateModule(project, sheet, domainList, project.getDataDomains());
					m.setNav(nav);
					project.addModule(m);
					project.setDataDomains(m.decorateDataDomains(project.getDataDomains()));
				}
				if (sheet.getSheetName().toLowerCase().contains("layout")) {
					LayoutComb lcm = translateLayout(project, sheet, domainList, project.getDataDomains());
					lcm.setTitles(project.getTitle(), project.getSubTitle(), project.getFooter());
					lcm.setTechnicalStack(project.getTechnicalstack());
					lcm.setNav(nav);
					project.addLayoutComb(lcm);
					nav.addLayout(lcm);
				}
				if (sheet.getSheetName().toLowerCase().contains("report")) {
					ReportComb rcm = translateReport(project, sheet, domainList, project.getDataDomains());
					rcm.setTitles(project.getTitle(), project.getSubTitle(), project.getFooter());
					rcm.setTechnicalStack(project.getTechnicalstack());
					rcm.setNav(nav);
					project.addReportComb(rcm);
					nav.addReport(rcm);
				}
			}catch (ValidateException ve) {
				combInfos.addAllCompileErrors(ve.getValidateInfo().getCompileErrors());
				combInfos.addAllCompileWarnings(ve.getValidateInfo().getCompileWarnings());
			}
		}
		ValidateInfo info00 = preValidateDomainList(domainList, ignoreWarning);
		ValidateInfo info01 = validateDomains(domainList, ignoreWarning);
		List<ValidateInfo> infos = new ArrayList<ValidateInfo>();
		infos.add(combInfos);
		infos.add(info0);
		infos.add(info01);
		infos.add(info00);

		for (Domain d : domainList) {
			if (!StringUtil.isBlank(project.getDomainSuffix()))
				d.setDomainSuffix(project.getDomainSuffix());
			if (!StringUtil.isBlank(project.getDaoSuffix()))
				d.setDaoSuffix(project.getDaoSuffix());
			if (!StringUtil.isBlank(project.getDaoimplSuffix()))
				d.setDaoimplSuffix(project.getDaoimplSuffix());
			if (!StringUtil.isBlank(project.getServiceSuffix()))
				d.setServiceSuffix(project.getServiceSuffix());
			if (!StringUtil.isBlank(project.getServiceimplSuffix()))
				d.setServiceimplSuffix(project.getServiceimplSuffix());
			if (!StringUtil.isBlank(project.getControllerSuffix()))
				d.setControllerSuffix(project.getControllerSuffix());
			if (!StringUtil.isBlank(project.getDomainNamingSuffix()))
				d.setDomainNamingSuffix(project.getDomainNamingSuffix());
			if (!StringUtil.isBlank(project.getControllerNamingSuffix()))
				d.setControllerNamingSuffix(project.getControllerNamingSuffix());
		}		

		project.setDomains(domainList);

		DBDefinitionGenerator dbdg;
		if (project.getDbType().equalsIgnoreCase("oracle")) {
			dbdg = new Oracle11gDBDefinitionGenerator();
		} else if (project.getDbType().equalsIgnoreCase("postgresql")
				|| project.getDbType().equalsIgnoreCase("pgsql")) {
			dbdg = new PgsqlDBDefinitionGenerator();
		} else {
			dbdg = new MysqlDBDefinitionGenerator();
		}
		dbdg.setDbName(project.getDbName());
		ApplicationContextXml axml = new ApplicationContextXml();
		axml.setTemplateDomain(domainList.get(0));

		decorateDropdowns(domainList);
		if (project.getPackageToken() == null || "".equals(project.getPackageToken())) {
			ValidateInfo info1 = new ValidateInfo();
			info1.addCompileError("没有设置PackageToken！");
			throw new ValidateException(info1);
		} else {
			String dbPrefix = project.getDbPrefix();
			for (int m = 0; m < domainList.size(); m++) {
				domainList.get(m).setDbPrefix(dbPrefix);
				domainList.get(m).setPackageToken(project.getPackageToken());
			}
		}
		List<Prism> prismList = generatePrismsByDomains(domainList, dbdg, project, ignoreWarning);
		TreeSet<SpringMVCController> mycontrollers = new TreeSet<SpringMVCController>();
		EasyUIHomePagePI homepage = new EasyUIHomePagePI(project.getLanguage());
		homepage.setTitles(project.getTitle(), project.getSubTitle(), project.getFooter());
		homepage.setTechnicalStack(project.getTechnicalstack());
		homepage.setNav(nav);
		project.setHomepage(homepage);

		for (Prism p : prismList) {
			p.setTitle(project.getTitle());
			p.setSubTitle(project.getSubTitle());
			p.setFooter(project.getFooter());
			p.setResolution(project.getResolution());
			p.setNav(project.getNav());

			for (PrismInterface page :p.getPages()) {
				page.setNav(nav);
				page.setTitles(project.getTitle(), project.getSubTitle(), project.getFooter());
			}

			SpringMVCController f = p.getController();
			if (!StringUtil.isBlank(project.getCrossOrigin())) {
				p.setCrossOrigin(project.getCrossOrigin());
				f.decorateCrossOrigin(project.getCrossOrigin());
			}
			p.setController(f);
			mycontrollers.add(f);

			// Mirgate from SGSCompiler
			Set<Pair> mtmSlaveNames = new TreeSet<Pair>();
			for (ManyToMany mtm : p.getDomain().getManyToManies()) {
				mtmSlaveNames.add(new Pair(p.getDomain().getStandardName(), mtm.getManyToManySalveName()));
			}
			p.setManyToManySlaveNames(mtmSlaveNames);
		}

		decorateMtmDomainList(project.getDataDomains(), domainList);
		dbdg.setDomains(domainList);
		
		project.decorateConfigFiles();

		axml.setDomainList(domainList);
		axml.setDbname(project.getDbName());
		axml.setDbUsername(project.getDbUsername());
		axml.setDbPassword(project.getDbPassword());
		axml.setEmptypassword(project.isEmptypassword());
		axml.setDbType(project.getDbType());

		axml.setControllers(mycontrollers);
		if (project.isEmptypassword()) {
			axml.setDbPassword("");
			axml.setEmptypassword(true);
		}
		List<String> packageToScanList = new ArrayList<String>();
		packageToScanList.add(project.getPackageToken() + ".domain");
		axml.setPackagesToScanList(packageToScanList);
		axml.setPutInsideSrcAndClasses(true);

		project.addDBDefinitionGenerator(dbdg);
		project.setPrisms(prismList);
		project.replaceConfigFile(axml);

		ValidateInfo info = basicValidateProject(project, ignoreWarning);
		infos.add(info);
		ValidateInfo finalinfo = ValidateInfo.mergeValidateInfo(infos, ignoreWarning);
		if (finalinfo.success(ignoreWarning)) {
			return project;
		} else {
			ValidateException em = new ValidateException(finalinfo);
			throw em;
		}
	}
	
	public void decorateMtms(Domain domain,List<Domain> domains) throws ValidateException{
		for (ManyToMany mtm:domain.getManyToManies()) {
			mtm.setMaster(domain);
			Domain slave = DomainUtil.findDomainInList(domains, mtm.getManyToManySalveName());
			if (slave == null) {
				System.out.println("JerryDebug:++"+mtm.getManyToManySalveName());
			}else {
				mtm.setSlave(slave);
			}
		}
	}
	
	public void decorateDomainsMtms(List<Domain> domains) throws ValidateException{
		for (Domain d:domains) {
			decorateMtms(d,domains);
		}
	}
	
	public Set<ManyToMany> getMtmsFromDomains(List<Domain> domains) throws ValidateException{
		long serial = 0L;
		Set<ManyToMany> mtms = new TreeSet<>(new ManyToManySerialComparator());
		for (Domain d:domains) {				
			Set<ManyToMany> mtmset = d.getManyToManies();
			for (ManyToMany mtm:mtmset) {
				mtm.setMaster(d);
				if (mtm.getSlave()!=null) {
					mtm.setSlave(mtm.getSlave());
				}else {
					ArrayList<Domain> targetDomains = new ArrayList<Domain>();
					targetDomains.addAll(domains);
					Domain slave = DomainUtil.findDomainInList(targetDomains, mtm.getManyToManySalveName());
					mtm.setSlave(slave);
				}
				mtm.setSerial(serial);
				serial += 1000L;
				mtms.add(mtm);
			}
		}
		return mtms;
	}

	public Module translateModule(Project project, HSSFSheet sheet, List<Domain> domains,
			List<List<Domain>> datadomains) throws Exception {
		String moduleName = readMetaField(sheet, "module", "mysql");
		if ("shiroauth".equalsIgnoreCase(moduleName)) {
			ShiroAuthExcelTranslator sat = new ShiroAuthExcelTranslator();
			return sat.translate(project, sheet, domains, datadomains);
		}
		return null;
	}

	public LayoutComb translateLayout(Project project, HSSFSheet sheet, List<Domain> domains,
			List<List<Domain>> datadomains) throws Exception {
		LayoutExcelTranslator let = new LayoutExcelTranslator();
		return let.translate(project, sheet, domains, datadomains);
	}

	public ReportComb translateReport(Project project, HSSFSheet sheet, List<Domain> domains,
			List<List<Domain>> datadomains) throws Exception {
		ReportExcelTranslator ret = new ReportExcelTranslator();
		return ret.translate(project, sheet, domains, datadomains);
	}

	public static ValidateInfo preValidateDomainList(List<Domain> lists, Boolean ignoreWarning) {
		List<ValidateInfo> infos = new ArrayList<ValidateInfo>();
		for (Domain d : lists) {
			try {
				infos.add(validateLegcyDomain(d, lists));
			} catch (ValidateException ve) {
				infos.add(ve.getValidateInfo());
			}
		}
		return ValidateInfo.mergeValidateInfo(infos, ignoreWarning);
	}

	public static ValidateInfo basicValidateProject(Project project, Boolean ignoreWarning) {
		List<Prism> prisms = project.getPrisms();
		List<Domain> domains = project.getDomains();
		return validateDomainsAndPrisms(domains, prisms, ignoreWarning);
	}

	public static ValidateInfo validateDomainsAndPrisms(List<Domain> domains, List<Prism> prisms,
			Boolean ignoreWarning) {
		// ValidateInfo validateInfo1 = validateDomains(domains);
		ValidateInfo validateInfo2 = validatePrisms(prisms);
		List<ValidateInfo> vList = new ArrayList<ValidateInfo>();
		// vList.add(validateInfo1);
		vList.add(validateInfo2);
		ValidateInfo validateInfo = ValidateInfo.mergeValidateInfo(vList, ignoreWarning);
		return validateInfo;
	}

	public static ValidateInfo validatePrisms(List<Prism> prisms) {
		ValidateInfo validateInfo = new ValidateInfo();
		List<Prism> targets = new ArrayList<Prism>();
		for (int i = 0; i < prisms.size(); i++) {
			for (int j = 0; j < targets.size(); j++) {
				if (prisms.get(i).getStandardName().equals(targets.get(j).getStandardName())) {
					validateInfo.addCompileWarning("棱柱" + prisms.get(i).getStandardName() + "重复。");
				} else {
					targets.add(prisms.get(i));
				}
			}
		}
		if (prisms != null) {
			for (int i = 0; i < prisms.size(); i++) {
				if (!prisms.get(i).getStandardName().equals(prisms.get(i).getDomain().getStandardName() + "Prism")) {
					validateInfo.addCompileWarning("棱柱" + prisms.get(i).getStandardName() + "的域对象"
							+ prisms.get(i).getDomain().getStandardName() + "没有正确设置。");
				}
			}
		}
		return validateInfo;
	}

	public static ValidateInfo validateDomains(List<Domain> domains, Boolean ignoreWarning) {
		ValidateInfo validateInfo = new ValidateInfo();
		for (int i = 0; i < domains.size(); i++) {
			if (domains.subList(i + 1, domains.size()).contains(domains.get(i))) {
				validateInfo.addCompileWarning("域对象" + domains.get(i).getStandardName() + "重复。");
			}
		}
		List<ValidateInfo> infos = new ArrayList<ValidateInfo>();
		infos.add(validateInfo);
		for (Domain d : domains) {
			ValidateInfo vd = validateDomain(d);
			infos.add(vd);
		}
		for (Domain d : domains) {
			ValidateInfo vd = validateDomainFields(d);
			infos.add(vd);
		}
		return ValidateInfo.mergeValidateInfo(infos, ignoreWarning);
	}

	public static ValidateInfo validateDomain(Domain domain) {
		ValidateInfo validateInfo = new ValidateInfo();
		if (StringUtil.isBlank(domain.getDomainId())) {
			validateInfo.addCompileWarning("域对象" + domain.getStandardName() + "的主键没有设置。");
		}
		if (StringUtil.isBlank(domain.getDomainName())) {
			validateInfo.addCompileWarning("域对象" + domain.getStandardName() + "的对象名字没有设置。");
		}
		if (StringUtil.isBlank(domain.getActive())) {
			validateInfo.addCompileWarning("域对象" + domain.getStandardName() + "的活跃字段没有设置。");
		}
		return validateInfo;
	}

	public static ValidateInfo validateDomainFields(Domain domain) {
		ValidateInfo validateInfo = new ValidateInfo();
		Set<String> fieldNames = new TreeSet<>();
		for (Field f : domain.getFields()) {
			if (fieldNames.contains(f.getFieldName())) {
				validateInfo.addCompileError("域对象" + domain.getStandardName() + "的字段" + f.getFieldName() + "重复。");
			} else {
				fieldNames.add(f.getFieldName());
			}
		}
		return validateInfo;
	}

	public static ValidateInfo validateLegcyDomain(Domain domain, List<Domain> lists) throws ValidateException {
		ValidateInfo validateInfo = new ValidateInfo();
		if (domain.isLegacy() && domain.getManyToManies() != null && domain.getManyToManies().size() > 0) {
			validateInfo.addCompileError("遗留域对象" + domain.getStandardName() + "不可作为多对多主对象。");
		}
		if (!domain.isLegacy() && domain.getManyToManies() != null) {
			for (ManyToMany mtm : domain.getManyToManies()) {
				Domain slave = DomainUtil.findDomainInList(lists, mtm.getManyToManySalveName());
				if (slave != null && slave.isLegacy())
					validateInfo.addCompileError(
							"域对象" + domain.getStandardName() + "的从对象" + mtm.getSlaveAlias() + "为遗留域对象，不可作为多对多从对象。");
			}
		}
		for (Field f : domain.getFieldsWithoutIdAndActive()) {
			if (f instanceof Dropdown) {
				Dropdown dp = (Dropdown) f;
				Domain target = DomainUtil.findDomainInList(lists, dp.getTargetName());
				if (target.isLegacy())
					validateInfo.addCompileError(
							"域对象" + domain.getStandardName() + "的字段" + f.getFieldName() + "为遗留域对象，不可作为一对多目标对象。");
			}
		}
		return validateInfo;
	}

	public Project translateProjectMetaData(HSSFSheet metaSheet, Project project) {
		String dbtype = readMetaField(metaSheet, "dbtype", "mysql");
		String projectName = readMetaField(metaSheet, "project", dbtype);
		String packageToken = readMetaField(metaSheet, "packagetoken", dbtype);
		String dbprefix = readMetaField(metaSheet, "dbprefix", dbtype);
		String dbname = readMetaField(metaSheet, "dbname", dbtype);
		String dbusername = readMetaField(metaSheet, "dbusername", dbtype);
		String dbpassword = readMetaField(metaSheet, "dbpassword", dbtype);
		String title = readMetaField(metaSheet, "title", dbtype);
		String subTitle = readMetaField(metaSheet, "subtitle", dbtype);
		String footer = readMetaField(metaSheet, "footer", dbtype);
		String crossOrigin = readMetaField(metaSheet, "crossorigin", dbtype);
		String resolution = readMetaField(metaSheet, "resolution", dbtype);

		String domainsuffix = readMetaField(metaSheet, "domainsuffix", dbtype).toLowerCase();
		String daosuffix = readMetaField(metaSheet, "daosuffix", dbtype).toLowerCase();
		String daoimplsuffix = readMetaField(metaSheet, "daoimplsuffix", dbtype).toLowerCase();
		String servicesuffix = readMetaField(metaSheet, "servicesuffix", dbtype).toLowerCase();
		String serviceimplsuffix = readMetaField(metaSheet, "serviceimplsuffix", dbtype).toLowerCase();
		String controllersuffix = readMetaField(metaSheet, "controllersuffix", dbtype).toLowerCase();
		String domainnamingsuffix = StringUtil.capFirst(readMetaField(metaSheet, "domainnamingsuffix", dbtype));
		String controllernamingsuffix = StringUtil.capFirst(readMetaField(metaSheet, "controllernamingsuffix", dbtype));

		String technicalstack = readMetaField(metaSheet, "technicalstack", dbtype);
		String language = readMetaField(metaSheet, "language", dbtype);
		String schema = readMetaField(metaSheet, "schema", dbtype);
		String frontBaseApi = readMetaField(metaSheet, "frontbaseapi", dbtype);

		if ("postgresql".equalsIgnoreCase(dbtype) || "pgsql".equalsIgnoreCase(dbtype))
			dbname = dbname.toLowerCase();

		project.setStandardName(projectName);
		project.setPackageToken(packageToken);
		project.setDbPrefix(dbprefix);
		project.setDbName(dbname);
		project.setDbUsername(dbusername);
		project.setDbPassword(dbpassword);
		project.setDbType(dbtype);
		project.setTechnicalstack(technicalstack);
		project.setTitle(title);
		project.setSubTitle(subTitle);
		project.setFooter(footer);
		project.setCrossOrigin(crossOrigin);
		project.setResolution(resolution);

		if (!StringUtil.isBlank(language))
			project.setLanguage(language);
		if (!StringUtil.isBlank(schema))
			project.setSchema(schema);

		if (!StringUtil.isBlank(domainsuffix))
			project.setDomainSuffix(domainsuffix);
		if (!StringUtil.isBlank(daosuffix))
			project.setDaoSuffix(daosuffix);
		if (!StringUtil.isBlank(daoimplsuffix))
			project.setDaoimplSuffix(daoimplsuffix);
		if (!StringUtil.isBlank(servicesuffix))
			project.setServiceSuffix(servicesuffix);
		if (!StringUtil.isBlank(serviceimplsuffix))
			project.setServiceimplSuffix(serviceimplsuffix);
		if (!StringUtil.isBlank(controllersuffix))
			project.setControllerSuffix(controllersuffix);
		if (!StringUtil.isBlank(domainnamingsuffix))
			project.setDomainNamingSuffix(domainnamingsuffix);
		if (!StringUtil.isBlank(controllernamingsuffix))
			project.setControllerNamingSuffix(controllernamingsuffix);
		if (!StringUtil.isBlank(frontBaseApi))
			project.setFrontBaseApi(frontBaseApi);
		return project;
	}

	public Prism translatePrism(HSSFSheet prismSheet) {
		Prism prism = new Prism();
		return prism;
	}

	public Domain translateDomain(HSSFSheet domainSheet, String dbType, Boolean ignoreWarning)
			throws ValidateException {
		Domain domain = new Domain();
		String domainName = readMetaField(domainSheet, "domain", dbType);
		if (domainName.contains("_"))
			domainName = StringUtil.capFirst(StringUtil.changeTableColumtoDomainField(domainName));
		String plural = readMetaField(domainSheet, "plural", dbType);
		if (plural.contains("_"))
			plural = StringUtil.capFirst(StringUtil.changeTableColumtoDomainField(plural));
		String tableprefix = readMetaField(domainSheet, "tableprefix", dbType);
		String domainlabel = readMetaField(domainSheet, "domainlabel", dbType);
		String verdeniesStr = readMetaField(domainSheet, "verbdenies", dbType);
		Cell metaFieldCell = locateKeyCell(domainSheet, "元字段类型", dbType);
		Cell fieldCell = locateKeyCell(domainSheet, "字段", dbType);
		Cell fieldTypeCell = locateKeyCell(domainSheet, "字段类型", dbType);
		Cell fieldLengthCell = locateKeyCell(domainSheet, "长度", dbType);
		Cell fieldFixNameCell = locateKeyCell(domainSheet, "固定名字", dbType);
		int fieldFixNameRow = fieldFixNameCell == null ? -1 : fieldFixNameCell.getRowIndex();
		Cell fieldLabelCell = locateKeyCell(domainSheet, "字段标签", dbType);
		Cell fieldDataCell = locateKeyCell(domainSheet, "数据", dbType);
		int fieldLengthRow = fieldLengthCell == null ? -1 : fieldLengthCell.getRowIndex();
		ValidateInfo info = new ValidateInfo();
		for (int i = metaFieldCell.getColumnIndex() + 1; i < domainSheet.getRow(metaFieldCell.getRowIndex())
				.getLastCellNum(); i++) {
			try {
				String metaField = readFieldMeta(domainSheet, i, metaFieldCell.getRowIndex(), dbType);
				if (!StringUtil.isBlank(metaField)
						&& (metaField.equalsIgnoreCase("field") || metaField.equalsIgnoreCase("id")
								|| metaField.equalsIgnoreCase("domainid") || metaField.equalsIgnoreCase("domainname")
								|| metaField.equalsIgnoreCase("active") || metaField.equalsIgnoreCase("activefield"))) {
					Field f = readDomainField(domainSheet, i, metaFieldCell.getRowIndex(), fieldCell.getRowIndex(),
							fieldTypeCell.getRowIndex(), fieldLengthRow, fieldFixNameRow, fieldLabelCell.getRowIndex(),
							domain, dbType, ignoreWarning);
					System.out.println("JerryDebug:FieldName:FixedName:" + f.getFieldName() + ":" + f.getFixedName());
					if (!StringUtil.isBlank(metaField) && metaField.equalsIgnoreCase("field")) {
						domain.addField(f);
					} else if (!StringUtil.isBlank(metaField)
							&& (metaField.equalsIgnoreCase("id") || metaField.equalsIgnoreCase("domainid"))) {
						domain.setDomainId(f);
					} else if (!StringUtil.isBlank(metaField)
							&& (metaField.equalsIgnoreCase("active") || metaField.equalsIgnoreCase("activefield"))) {
						domain.setActive(f);
					} else if (!StringUtil.isBlank(metaField) && (metaField.equalsIgnoreCase("domainname")
							|| metaField.equalsIgnoreCase("activefield"))) {
						domain.setDomainName(f);
					}
				} else if (!StringUtil.isBlank(metaField) && metaField.equalsIgnoreCase("dropdown")) {
					Dropdown dp = readDropdown(domainSheet, i, metaFieldCell.getRowIndex(), fieldCell.getRowIndex(),
							fieldTypeCell.getRowIndex(), fieldLabelCell.getRowIndex(), ignoreWarning);
					domain.addField(dp);
					domain.putFieldLabel(dp.getFieldName(), dp.getLabel());
				} else if (!StringUtil.isBlank(metaField) && metaField.equalsIgnoreCase("manytomanyslave")) {
					String mtmname = readManyToManyName(domainSheet, i, metaFieldCell.getRowIndex(),
							fieldCell.getRowIndex(), fieldTypeCell.getRowIndex(), fieldLabelCell.getRowIndex());
					String mtmAlias = readManyToManyAlias(domainSheet, i, metaFieldCell.getRowIndex(),
							fieldCell.getRowIndex(), fieldTypeCell.getRowIndex(), fieldLabelCell.getRowIndex());
					String mtmAliasLabel = readManyToManyAliasLabel(domainSheet, i, metaFieldCell.getRowIndex(),
							fieldCell.getRowIndex(), fieldTypeCell.getRowIndex(), fieldLabelCell.getRowIndex());
					ManyToMany mtm = new ManyToMany();
					if (!StringUtil.isBlank(mtmname)) {
						mtm = new ManyToMany(domainName, mtmname);
					}
					if (!StringUtil.isBlank(mtmAlias)) {
						mtm.setSlaveAlias(mtmAlias);
						mtm.setSlaveAliasLabel(mtmAliasLabel);
						mtm.setStandardName(mtmAlias);
					}
					domain.addManyToMany(mtm);
				} else {
					if (!validateMetaField(metaField)) {
						info.addCompileError("域对象" + domainName + "元字段" + metaField + "设置错误！");
					}
				}
			} catch (ValidateException e) {
				info.addAllCompileErrors(e.getValidateInfo().getCompileErrors());
				info.addAllCompileWarnings(e.getValidateInfo().getCompileWarnings());
			}
		}

		if (!info.success(ignoreWarning))
			throw new ValidateException(info);
		domain.setStandardName(domainName);
		if (!StringUtil.isBlank(plural))
			domain.setPlural(plural);
		if (!StringUtil.isBlank(tableprefix))
			domain.setTablePrefix(tableprefix);
		if (!StringUtil.isBlank(domainlabel))
			domain.setLabel(domainlabel);
		if (!StringUtil.isBlank(verdeniesStr))
			domain.setVerbDeniesStr(verdeniesStr);
		return domain;
	}

	public boolean validateMetaField(String fieldMeta) {
		switch (fieldMeta) {
		case "id":
		case "domainname":
		case "activefield":
		case "field":
		case "dropdown":
		case "manytomanyslave":
			return true;
		default:
			return false;
		}
	}

	public boolean validateFieldType(String fieldMeta, String fieldType) {
		if ("dropdown".equals(fieldMeta) || "manytomanyslave".equals(fieldMeta)) {
			return true;
		} else {
			switch (fieldType) {
			case "int":
			case "Integer":
			case "long":
			case "Long":
			case "boolean":
			case "Boolean":
			case "double":
			case "Double":
			case "float":
			case "Float":
			case "string":
			case "String":
			case "decimal":
			case "Decimal":
			case "BigDecimal":
			case "image":
			case "Image":
				return true;
			default:
				return false;
			}
		}
	}

	public boolean validateSqlFieldType(String fieldType) {
		fieldType = fieldType.toLowerCase();
		switch (fieldType) {
		case "char":
		case "nchar":
		case "varchar":
		case "varchar2":
		case "nvarchar":
		case "tinytext":
		case "longtext":
		case "text":
		case "ntext":
		case "tinyint":
		case "smallint":
		case "mediumint":
		case "bigint":
		case "numeric":
		case "decimal":
		case "real":
			return true;
		default:
			return false;
		}
	}

	public String parseSqlFieldType(String fieldType) {
		String myfieldType = fieldType.toLowerCase();
		switch (myfieldType) {
		case "char":
		case "nchar":
		case "varchar":
		case "varchar2":
		case "nvarchar":
		case "tinytext":
		case "longtext":
		case "text":
		case "ntext":
			return "String";
		case "tinyint":
		case "smallint":
		case "mediumint":
			return "Integer";
		case "bigint":
			return "Long";
		case "numeric":
		case "decimal":
		case "real":
			return "Double";
		default:
			return fieldType;
		}
	}

	public Field readDomainField(HSSFSheet sheet, int columIndex, int metaFieldIndex, int fieldIndex,
			int fieldTypeIndex, int fieldLengthIndex, int fieldFixNameIndex, int fieldLabelIndex, Domain domain,
			String dbType, Boolean ignoreWarning) throws ValidateException {
		Field f = new Field();
		String domainName = readMetaField(sheet, "domain", dbType);
		String metafield = readFieldMeta(sheet, columIndex, metaFieldIndex, dbType);
		String fieldname = sheet.getRow(fieldIndex).getCell(columIndex).getStringCellValue().trim().replace("\'", "");
		if (fieldname.contains("_"))
			fieldname = StringUtil.changeTableColumtoDomainField(fieldname);
		String fixname = fieldFixNameIndex < 0 ? ""
				: sheet.getRow(fieldFixNameIndex).getCell(columIndex).getStringCellValue().trim().replace("\'", "");
		if (fieldname.contains("_"))
			fieldname = StringUtil.changeTableColumtoDomainField(fieldname);
		String fieldType = sheet.getRow(fieldTypeIndex).getCell(columIndex).getStringCellValue().trim().replace("\'",
				"");
		String fieldLength = fieldLengthIndex < 0 ? ""
				: getCellStringValue(sheet.getRow(fieldLengthIndex).getCell(columIndex), dbType).trim().replace("\'",
						"");
		String fieldLabel = getCellStringValue(sheet.getRow(fieldLabelIndex).getCell(columIndex), dbType).replace("\'",
				"");
		long fieldSerial = columIndex * 100;
		ValidateInfo info = new ValidateInfo();
		if (!validateMetaField(metafield)) {
			info.addCompileError("域对象" + domainName + "元字段" + metafield + "设置错误！");
		}
		if (validateSqlFieldType(fieldType)) {
			info.addCompileWarning("域对象" + domainName + "字段类型" + fieldType + "为SQL类型！");
			fieldType = parseSqlFieldType(fieldType);
		}
		if (!validateFieldType(metafield, fieldType)) {
			info.addCompileError("域对象" + domainName + "字段类型" + fieldType + "设置错误！");
		}
		if (!StringUtil.isLowerCaseLetter(fieldname)) {
			info.addCompileError("域对象" + domainName + "字段" + fieldname + "未使用小写英文字母开头！");
		}
		if (fieldname.length() >= 2 && !StringUtil.isLowerCaseLetterPosition(fieldname, 1)) {
			info.addCompileError("域对象" + domainName + "字段" + fieldname + "第二个字母未使用小写英文字母！");
		}
		if (isForbidden(fieldname)) {
			info.addCompileError("域对象" + domainName + "字段" + fieldname + "使用了被禁止的单词！");
		}
		if (isSqlKeyword(fieldname)) {
			info.addCompileError("域对象" + domainName + "字段" + fieldname + "使用了SQL关键字！");
		}
		if ("Oracle".equalsIgnoreCase(dbType)&&isOracleKeyword(fieldname)) {
			info.addCompileError("域对象" + domainName + "字段" + fieldname + "使用了Oracle关键字！");
		}

		if (!StringUtil.isBlank(metafield)
				&& (metafield.equalsIgnoreCase("id") || metafield.equalsIgnoreCase("domianid")
						|| metafield.equalsIgnoreCase("domainname") || metafield.equalsIgnoreCase("active")
						|| metafield.equalsIgnoreCase("activefield") || metafield.equalsIgnoreCase("field"))) {
			if (!StringUtil.isBlank(fieldType))
				f.setFieldType(fieldType);
			if (!StringUtil.isBlank(fieldLength))
				f.setLengthStr(fieldLength);
			if (!StringUtil.isBlank(fieldLabel)) {
				f.setLabel(fieldLabel);
				domain.putFieldLabel(fieldname, fieldLabel);
			}
			if (!StringUtil.isBlank(fieldname))
				f.setFieldName(fieldname);
			if (!StringUtil.isBlank(fixname)) {
				f.setFixedName(fixname);
			} else {
				f.setFixedName(fieldname);
			}
			System.out.println("JerryDebug:FixedName:" + fixname);
			if (!info.success(ignoreWarning))
				throw new ValidateException(info);
			else {
				f.setSerial(fieldSerial);
				return f;
			}

		} else {
			info.addCompileError("字段解析错误");
			throw new ValidateException(info);
		}
	}

	public Dropdown readDropdown(HSSFSheet sheet, int columIndex, int metaFieldIndex, int fieldIndex,
			int fieldTypeIndex, int fieldLabelIndex, Boolean ignoreWarning) throws ValidateException {
		String metafield = sheet.getRow(metaFieldIndex).getCell(columIndex).getStringCellValue().trim();
		String fieldname = sheet.getRow(fieldIndex).getCell(columIndex).getStringCellValue().trim().replace("\'", "");
		if (fieldname.contains("_"))
			fieldname = StringUtil.changeTableColumtoDomainField(fieldname);
		String fieldType = sheet.getRow(fieldTypeIndex).getCell(columIndex).getStringCellValue().trim().replace("\'",
				"");
		String fieldLabel = sheet.getRow(fieldLabelIndex).getCell(columIndex).getStringCellValue().trim().replace("\'",
				"");
		ValidateInfo info = new ValidateInfo();
		if (!StringUtil.isLowerCaseLetter(fieldname)) {
			info.addCompileError("下拉列表字段" + fieldname + "未使用小写英文字母开头！");
		}
		if (metafield != null && !metafield.equals("") && metafield.equalsIgnoreCase("dropdown")) {
			Dropdown dp = new Dropdown(fieldType);
			dp.setAliasName(fieldname);
			dp.setFieldName(dp.getAliasName());
			dp.setLabel(fieldLabel);
			if (!info.success(ignoreWarning))
				throw new ValidateException(info);
			else
				return dp;
		} else {
			info.addCompileError("字段解析错误");
			throw new ValidateException(info);
		}
	}

	public String readFieldMeta(HSSFSheet sheet, int columIndex, int metaFieldIndex, String dbType) {
		String metafield = getCellStringValue(sheet.getRow(metaFieldIndex).getCell(columIndex), dbType);
		return metafield;
	}

	public String readManyToManyName(HSSFSheet sheet, int columIndex, int metaFieldIndex, int fieldIndex,
			int fieldTypeIndex, int fieldLabelIndex) throws ValidateException {
		String metafield = sheet.getRow(metaFieldIndex).getCell(columIndex).getStringCellValue().trim();
		String fieldType = sheet.getRow(fieldTypeIndex).getCell(columIndex).getStringCellValue().trim();
		if (fieldType.contains("_"))
			fieldType = StringUtil.capFirst(StringUtil.changeTableColumtoDomainField(fieldType));
		fieldType = StringUtil.capFirst(fieldType);
		if (metafield != null && !metafield.equals("") && metafield.equalsIgnoreCase("manytomanyslave")) {
			return fieldType;
		} else {
			throw new ValidateException("字段解析错误");
		}
	}

	public String readManyToManyAlias(HSSFSheet sheet, int columIndex, int metaFieldIndex, int fieldIndex,
			int fieldTypeIndex, int fieldLabelIndex) throws ValidateException {
		String metafield = sheet.getRow(metaFieldIndex).getCell(columIndex).getStringCellValue().trim();
		String field = sheet.getRow(fieldIndex).getCell(columIndex).getStringCellValue().trim();
		if (field.contains("_"))
			field = StringUtil.changeTableColumtoDomainField(field);
		field = StringUtil.capFirst(field);
		if (metafield != null && !metafield.equals("") && metafield.equalsIgnoreCase("manytomanyslave")) {
			return field;
		} else {
			throw new ValidateException("字段解析错误");
		}
	}

	public String readManyToManyAliasLabel(HSSFSheet sheet, int columIndex, int metaFieldIndex, int fieldIndex,
			int fieldTypeIndex, int fieldLabelIndex) throws ValidateException {
		String metafield = sheet.getRow(metaFieldIndex).getCell(columIndex).getStringCellValue().trim();
		String field = sheet.getRow(fieldLabelIndex).getCell(columIndex).getStringCellValue().trim();
		if (metafield != null && !metafield.equals("") && metafield.equalsIgnoreCase("manytomanyslave")) {
			return field;
		} else {
			throw new ValidateException("字段解析错误");
		}
	}

	public String readMetaField(HSSFSheet metaSheet, String key, String dbType) {
		Cell c = locateKeyCell(metaSheet, key, dbType);
		if (c == null)
			return "";
		else
			// return
			// metaSheet.getRow(c.getRowIndex()).getCell(c.getColumnIndex() +
			// 1).getStringCellValue();
			return this.getCellStringValue(metaSheet.getRow(c.getRowIndex()).getCell(c.getColumnIndex() + 1), dbType)
					.trim();
	}

	public Cell locateKeyCell(HSSFSheet metaSheet, String key, String dbType) {
		int rowbegin = metaSheet.getFirstRowNum();
		int rowend = metaSheet.getLastRowNum();
		for (int i = rowbegin; i <= rowend; i++) {
			Row r = metaSheet.getRow(i);
			if (r != null) {
				for (int j = r.getFirstCellNum(); j <= r.getLastCellNum(); j++) {
					Cell c = r.getCell(j);
					if (c != null && this.getCellStringValue(c, dbType).equalsIgnoreCase(key))
						return c;
				}
			}
		}
		return null;
	}

	public List<Domain> readDomainListWithData(HSSFSheet sheet, Domain templateDomain, String dbtype,
			boolean ignoreWarning) throws ValidateException {
		List<Domain> resultList = new ArrayList<Domain>();
		Cell metaCell = locateKeyCell(sheet, "元字段类型", dbtype);
		Cell dataCell = locateKeyCell(sheet, "数据", dbtype);
		Cell fieldCell = locateKeyCell(sheet, "字段", dbtype);

		ValidateInfo vInfo = new ValidateInfo();
		if (dataCell != null) {
			for (int i = dataCell.getRowIndex(); i < findOutLastDataRowIndex(sheet, findOutIdColIndex(sheet, dbtype),
					dataCell.getRowIndex(), dbtype); i++) {
				Domain targetDomain = (Domain) templateDomain.deepClone();
				for (Field f : templateDomain.getFields()) {
					if (f instanceof Dropdown) {
						Dropdown dp = (Dropdown) f;
						String fieldValue = StringUtil.filterSingleQuote(
								readDomainFieldValue(sheet, dp.getAliasName(), fieldCell.getColumnIndex() + 1,
										metaCell.getRowIndex(), fieldCell.getRowIndex(), i, dbtype));
						if (!DomainUtil.validateId(fieldValue))
							vInfo.addCompileError(
									"域对象" + targetDomain.getStandardName() + "的下拉列表" + f.getFieldName() + "值有错！");
						if (!StringUtil.isBlank(fieldValue))
							targetDomain.setFieldValue(dp.getAliasName(), fieldValue);
						else
							targetDomain.setFieldValue(dp.getAliasName(), fieldValue);
					} else {
						String fieldValue = StringUtil.filterSingleQuote(
								readDomainFieldValue(sheet, f.getFieldName(), fieldCell.getColumnIndex() + 1,
										metaCell.getRowIndex(), fieldCell.getRowIndex(), i, dbtype));
						if (targetDomain.getDomainId() != null
								&& f.getFieldName().equals(targetDomain.getDomainId().getFieldName())
								&& !DomainUtil.validateId(fieldValue))
							vInfo.addCompileError(
									"域对象" + targetDomain.getStandardName() + "的主键" + f.getFieldName() + "值有错！");
						if (!StringUtil.isBlank(fieldValue))
							targetDomain.getField(f.getFieldName()).setFieldValue(fieldValue);
						else
							targetDomain.getField(f.getFieldName()).setFieldValue("");
					}
				}
				for (ManyToMany mtm : targetDomain.getManyToManies()) {
					String fieldValue = StringUtil.filterSingleQuote(readDomainFieldValue(sheet, mtm.getSlaveAlias(),
							fieldCell.getColumnIndex() + 1, metaCell.getRowIndex(), fieldCell.getRowIndex(), i, dbtype));
	
					mtm.setMaster(targetDomain);
					mtm.setValues(fieldValue);
					if (targetDomain.hasDomainId())
						mtm.setMasterValue(targetDomain.getDomainId().getFieldValue());
					else
						throw new ValidateException("遗留域对象" + targetDomain.getStandardName() + "不可作为多对多主对象。");
				}
				resultList.add(targetDomain);
			}
		}
		if (!vInfo.isSuccess(ignoreWarning))
			throw new ValidateException(vInfo);
		else
			return resultList;
	}

	public void decorateMtmDomainList(List<List<Domain>> dataDomainList, List<Domain> allDomainList) throws Exception {
		for (List<Domain> targets : dataDomainList) {
			for (Domain targetDomain : targets) {
				for (ManyToMany mtm : targetDomain.getManyToManies()) {
					mtm.setSlave(findDomainFromListByStandardName(allDomainList, mtm.getManyToManySalveName()));
				}
			}
		}
	}

	public int findOutIdColIndex(HSSFSheet sheet, String dbType) {
		Cell metaFieldCell = locateKeyCell(sheet, "元字段类型", dbType);
		for (int i = metaFieldCell.getColumnIndex() + 1; i < sheet.getRow(metaFieldCell.getRowIndex())
				.getLastCellNum(); i++) {
			if (sheet.getRow(metaFieldCell.getRowIndex()).getCell(i).getStringCellValue().equals("id")) {
				return i;
			}
		}
		return metaFieldCell.getColumnIndex() + 1;
	}

	public int findOutLastDataRowIndex(HSSFSheet sheet, int idColIndex, int beginRowIndex, String dbtype) {
		for (int i = beginRowIndex; i <= sheet.getLastRowNum(); i++) {
			if (sheet.getRow(i) == null || sheet.getRow(i).getCell(idColIndex) == null
					|| StringUtil.isBlank(getCellStringValue(sheet.getRow(i).getCell(idColIndex), dbtype)))
				return i;
		}
		return sheet.getLastRowNum() + 1;
	}

	public String readDomainFieldValue(HSSFSheet sheet, String fieldName, int beginColIndex, int metaFieldRowIndex,
			int fieldNameRowIndex, int rowIndex, String dbtype) throws ValidateException {
		for (int i = beginColIndex; i < sheet.getRow(fieldNameRowIndex).getLastCellNum(); i++) {
			Cell metac = sheet.getRow(metaFieldRowIndex).getCell(i);
			Cell c = sheet.getRow(fieldNameRowIndex).getCell(i);
			String metaField = metac.getStringCellValue();
			String cellfieldName = c.getStringCellValue();
			if (cellfieldName.contains("_"))
				cellfieldName = StringUtil.changeTableColumtoDomainField(cellfieldName);
			if (metaField.equalsIgnoreCase("manytomanyslave")) {
				cellfieldName = StringUtil.capFirst(cellfieldName);
			} else {
				cellfieldName = StringUtil.lowerFirst(cellfieldName);
			}
			if (!StringUtil.isBlank(cellfieldName) && cellfieldName.equals(fieldName)) {
				return getCellStringValue(sheet.getRow(rowIndex).getCell(i), dbtype);
			}
		}
		return "";
	}

	public String getCellStringValue(Cell c, String dbtype) {
		if (c == null)
			return "";
		if (c.getCellType() == CellType.STRING) {
			String retVal = c.getStringCellValue();
			if (!StringUtil.isBlank(retVal) && retVal.charAt(0) == '\'')
				return retVal.substring(1, retVal.length());
			else if (StringUtil.isBlank(retVal))
				return "";
			else
				return retVal;
		}

		else if (c.getCellType() == CellType.NUMERIC) {
			short format = c.getCellStyle().getDataFormat();
			if (format == 14 || format == 31 || format == 57 || format == 58) {
				DateFormat formater = new SimpleDateFormat("yyyy-MM-dd");
				Date date = DateUtil.getJavaDate(c.getNumericCellValue());
				String value = formater.format(date);
				return value;
			} else if (format == 20 || format == 32) {
				DateFormat formater = new SimpleDateFormat("HH:mm");
				Date date = DateUtil.getJavaDate(c.getNumericCellValue());
				String value = formater.format(date);
				return value;
			}
			double dis = c.getNumericCellValue() - Math.round(c.getNumericCellValue());
			if (dis > 0.0001d) {
				return "" + c.getNumericCellValue();
			} else {
				return "" + (long) Math.round(c.getNumericCellValue());
			}
		} else if ((StringUtil.isBlank(dbtype) || dbtype.equalsIgnoreCase("mysql")
				|| dbtype.equalsIgnoreCase("mariadb")|| dbtype.equalsIgnoreCase("postgresql")|| dbtype.equalsIgnoreCase("pgsql")) && c.getCellType() == CellType.BOOLEAN) {
			return "" + c.getBooleanCellValue();
		} else if ((!StringUtil.isBlank(dbtype) && dbtype.equalsIgnoreCase("oracle"))
				&& c.getCellType() == CellType.BOOLEAN) {
			return "" + BooleanUtil.parseBooleanInt("" + c.getBooleanCellValue());
		} else if (c.getCellType() == CellType.FORMULA) {
			if (StringUtil.isBlank(dbtype) || dbtype.equalsIgnoreCase("mysql") || dbtype.equalsIgnoreCase("mariadb") || dbtype.equalsIgnoreCase("postgresql") || dbtype.equalsIgnoreCase("pgsql")) {
				String fml = c.getCellFormula();
				if (fml.equalsIgnoreCase("TRUE"))
					return "true";
				else if (fml.equalsIgnoreCase("FALSE"))
					return "false";
				else
					return "";
			} else if (!StringUtil.isBlank(dbtype) && dbtype.equalsIgnoreCase("oracle")) {
				String fml = c.getCellFormula();
				if (fml.equalsIgnoreCase("TRUE"))
					return "1";
				else if (fml.equalsIgnoreCase("FALSE)"))
					return "0";
				else
					return "";
			}
			return "";
		} else {
			return "";
		}
	}

	public static void main(String[] args) {
		try {
			InputStream is = new FileInputStream(
					"/home/jerry/git/LayUIGenerator/LayUIGenerator/exceltemplates/ShiroAuth.xls");
			POIFSFileSystem fs = new POIFSFileSystem(is);
			HSSFWorkbook wb = new HSSFWorkbook(fs);

			ProjectExcelWorkBook pwb = new ProjectExcelWorkBook();
			Project pj = pwb.translate(wb, true);

			List<Domain> ds = pj.getDomains();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
